#include "main.h"
#include <unistd.h>

int 	UART_FD = -1;

static uint8_t set_opt(int fd, uint32_t baudRate, uint8_t wordlength, char parity, uint8_t stopBit)
{
	struct termios opt;

	/*Get serial port attribute structure object*/
	if (tcgetattr(fd, &opt) != 0)
	{
		printf("serial port error!\n");
		return FALSE;
	}

	/*Sequence does not occupy the serial port, receive enable**/
	opt.c_cflag |= CLOCAL | CREAD;

	/*Configure baud rate*/
	switch (baudRate)
	{
	case 2400:
		cfsetispeed(&opt, B2400);
		cfsetospeed(&opt, B2400);
		break;
	case 4800:
		cfsetispeed(&opt, B4800);
		cfsetospeed(&opt, B4800);
		break;
	case 9600:
		cfsetispeed(&opt, B9600);
		cfsetospeed(&opt, B9600);
		break;
	case 115200:
		cfsetispeed(&opt, B115200);
		cfsetospeed(&opt, B115200);
		break;
	default:
		cfsetispeed(&opt, B9600);
		cfsetospeed(&opt, B9600);
		break;
	}

	opt.c_cflag &= ~CSIZE;

	switch (wordlength)
	{
	case 7:
		opt.c_cflag |= CS7;
		break;
	case 8:
		opt.c_cflag |= CS8;
		break;
	}

	switch (parity)
	{
	/*Odd check*/
	case 'o':
	case 'O':
		opt.c_cflag |= PARENB;			 //Parity enable
		opt.c_iflag |= (INPCK | ISTRIP); //Parity enable,Remove parity bits
		opt.c_cflag |= PARODD;			 //Use odd check instead of even check
		break;
	/*Even check*/
	case 'e':
	case 'E':
		opt.c_cflag |= PARENB;
		opt.c_iflag |= (INPCK | ISTRIP);
		opt.c_cflag &= ~PARODD;

		break;
	/*None check*/
	case 'n':
	case 'N':
		opt.c_cflag &= ~PARENB;
		opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
		opt.c_oflag &= ~OPOST;							/*Output*/
		break;
	}

	switch (stopBit)
	{
	case 1:
		opt.c_cflag &= ~CSTOPB;
		break;
	case 2:
		opt.c_cflag |= CSTOPB;
		break;
	}
	/*Set the waiting time and minimum receive characters*/
	opt.c_cc[VTIME] = 0;
	opt.c_cc[VMIN] = 0;

	opt.c_cflag &= ~HUPCL;
	opt.c_iflag &= ~INPCK;
	opt.c_iflag |= IGNBRK;
	opt.c_iflag &= ~ICRNL;
	opt.c_iflag &= ~IXON;
	opt.c_lflag &= ~IEXTEN;
	opt.c_lflag &= ~ECHOK;
	opt.c_lflag &= ~ECHOCTL;
	opt.c_lflag &= ~ECHOKE;
	opt.c_oflag &= ~ONLCR;

	/*Clear all the data that is happening*/
	tcflush(fd, TCIFLUSH);
	tcflush(fd, TCIOFLUSH);

	if ((tcsetattr(fd, TCSANOW, &opt)) != 0)
	{
		printf("serial set error!\n");
		return FALSE;
	}

	return TRUE;
}



/**
  * @brief  init uart
  * @param  uart_port:
  * @param  baudRate:
  * @param  wordlength:
  * @param  parity:
  * @param  stopBit:
  * @retval Success return TRUE if not return FALSE
  */
uint8_t uart_init(char *uart_port, uint32_t baudRate, uint8_t wordlength, char parity, uint8_t stopBit)
{
	UART_FD = open(uart_port, O_RDWR | O_NOCTTY | O_NDELAY);

	if ( UART_FD == -1)
	{
		printf("open_port: Unable to open: %s\n", uart_port);
		return FALSE;
	}
	else
	{
		if (set_opt(UART_FD, baudRate, wordlength, parity, stopBit) != TRUE)
		{
			printf("open_port: set baud rate failed!\n");
			return FALSE;
		}

	}
	
	return TRUE;
}

uint8_t uart_destory(void)
{
	if (close(UART_FD) < 0)
	{
		return FALSE;
	}

	return TRUE;
}

uint16_t serial_recv(uint8_t *buffer, uint16_t len)
{
	uint16_t read_num = 0;

	if ((len) && (buffer != NULL))
	{
		read_num = read(UART_FD, buffer, len);		
	}

	return read_num;
}

uint16_t serial_send(uint8_t *buffer, uint16_t len)
{
	uint16_t write_num = 0;

	if ((len) && (buffer != NULL))
	{
		write_num = write(UART_FD, buffer, len);
	}

	return write_num;
}
